spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1import { ImageResponse } from 'next/og';2import { t } from '@/i18n';3import { api, safe } from '@/lib/api';4import { displayValue } from '@/lib/format';5import { OG_INK2, OG_INK3, OG_RULE, OG_SIZE_H, OG_SIZE_W, OgFrame, OgWordmark } from '../../og-shared';67export const alt = 'Country statistics on CountryAtlas';8export const size = { width: OG_SIZE_W, height: OG_SIZE_H };9export const contentType = 'image/png';10export const revalidate = 3600;1112/** Per-country social image: flag + name + three headline values (population, GDP per capita, life expectancy). */13export default async function CountryOgImage({ params }: { params: Promise<{ slug: string }> }) {14 const { slug } = await params;15 const data = await safe(api.country(slug));16 const c = data?.country;17 const name = c?.name ?? slug.replace(/-/g, ' ');18 const pick = (id: string) => data?.headline.find((m) => m.indicator === id && m.has_data) ?? null;19 const facts = [pick('population'), pick('gdp-per-capita'), pick('life-expectancy')].filter((m): m is NonNullable<typeof m> => !!m).slice(0, 3);20 const sub = [c?.capital, c?.region_name, c?.income_name].filter(Boolean).join(' · ');21 return new ImageResponse(22 (23 <OgFrame>24 <OgWordmark size={28} />25 <div style={{ display: 'flex', alignItems: 'center', gap: 28, marginTop: 56 }}>26 <div style={{ fontSize: 120, lineHeight: 1, display: 'flex' }}>{c?.flag ?? ''}</div>27 <div style={{ display: 'flex', flexDirection: 'column' }}>28 <div style={{ fontSize: 68, fontWeight: 600, letterSpacing: -1.5, lineHeight: 1.05 }}>{name}</div>29 {sub ? <div style={{ marginTop: 10, fontSize: 24, color: OG_INK2 }}>{sub}</div> : null}30 </div>31 </div>32 <div style={{ display: 'flex', gap: 48, marginTop: 'auto', paddingTop: 24, borderTop: `1px solid ${OG_RULE}` }}>33 {facts.length === 0 ? (34 <div style={{ fontSize: 24, color: OG_INK2 }}>{t('country.description', { name }).split(':')[1]?.trim() ?? ''}</div>35 ) : null}36 {facts.map((m) => (37 <div key={m.indicator} style={{ display: 'flex', flexDirection: 'column' }}>38 <div style={{ fontSize: 18, color: OG_INK3, textTransform: 'uppercase', letterSpacing: 1.5 }}>{m.indicator_name ?? m.indicator}</div>39 <div style={{ fontSize: 44, fontWeight: 600, marginTop: 6 }}>{displayValue(m.value, m, m.formatted)}</div>40 <div style={{ fontSize: 18, color: OG_INK3, marginTop: 2 }}>{String(m.year ?? '')}</div>41 </div>42 ))}43 </div>44 <div style={{ position: 'absolute', right: 64, bottom: 24, fontSize: 20, color: OG_INK3 }}>{t('og.site')}</div>45 </OgFrame>46 ),47 { ...size },48 );49}50